from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
# Create your views here.
from carts.serializers import CartSerializers, SKUSerializers, CartDeleteSerializers, CartSelectedSerializers
from django_redis import get_redis_connection
import pickle,base64

from goods.models import SKU


class CartsView(APIView):


    def perform_authentication(self, request):
        # 在调用post方法之前先不进行用户验证
        pass

    def post(self,request):
        '''
        保存购物车
        :param request:
        :return:
        '''

        # 1,获取前端数据
        data = request.data

        # 2,验证数据
        ser = CartSerializers(data=data)
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        print(ser.errors)

        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']


        # 判断用户是否登录
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 用户已登录
            # 1,建立缓存链接
            conn = get_redis_connection('cart')

            # 2,保存hash类型和集合类型
            conn.hincrby('cart_%s'%user.id,sku_id,count)
            if selected:
                conn.sadd('cart_selected_%s'%user.id,sku_id)
            # 3,返回结果
            return Response('ok')

        else:
            # 1,先判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                # 2, 没有cookie定义一个空字典
                cart = {}

            # 3,有cookie获取cookie值累加
            sku_dict = cart.get(sku_id)
            if sku_dict:
                count += int(sku_dict['count'])

            cart[sku_id] = {
                'count':count,
                'selected':selected
            }
            # 4,将新的字典数据写入cookie
            response = Response('ok')
            # 加密写入后的字典
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            response.set_cookie('cart_cookie',cart_cookie,max_age=60*60*24*7)

            # 5,返回结果
            return response

    def get(self, request):
        '''
        获取购物车
        :param request:
        :return:
        '''

        # 判断用户是否登录
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 用户已登录
            # 1,建立缓存链接
            conn = get_redis_connection('cart')

            # 2,保存hash类型和集合类型
            sku_id_count = conn.hgetall('cart_%s' % user.id)
            sku_selected = conn.smembers('cart_selected_%s' % user.id)
            # 转化为完整的购物车数据
            cart = {}
            for sku_id,count in sku_id_count.items():
                cart[int(sku_id)] = {
                    'count':int(count),
                    'selected':sku_id in sku_selected
                }

        # 未登录
        else:
            # 1,先判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                # 2, 没有cookie定义一个空字典
                cart = {}

        skus = SKU.objects.filter(id__in=cart.keys())

        for sku in skus:
            sku.count = cart[sku.id]['count']
            sku.selected = cart[sku.id]['selected']

        ser = SKUSerializers(skus,many=True)

        return Response(ser.data)

    def put(self,request):
        '''
        修改购物车
        :param request:
        :return:
        '''

        # 1,获取前端数据
        data = request.data

        # 2,验证数据
        ser = CartSerializers(data=data)
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        print(ser.errors)

        sku_id = ser.validated_data['sku_id']
        count = ser.validated_data['count']
        selected = ser.validated_data['selected']


        # 判断用户是否登录
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 用户已登录
            # 1,建立缓存链接
            conn = get_redis_connection('cart')

            # 2,更新hash类型和集合类型
            conn.hset('cart_%s'%user.id,sku_id,count)
            # 对选中状态判断
            if selected:
                conn.sadd('cart_selected_%s'%user.id,sku_id)
            else:
                conn.srem('cart_selected_%s' % user.id, sku_id)
            # 3,返回结果
            return Response(ser.data)

        # 未登录
        else:
            # 1,先判断是否有cookie存在
            cart_cookie = request.COOKIES.get('cart_cookie')
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
            else:
                # 2, 没有cookie定义一个空字典
                cart = {}

            cart[sku_id] = {
                'count':count,
                'selected':selected
            }
            # 4,将新的字典数据写入cookie
            response = Response(ser.data)
            # 加密写入后的字典
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            response.set_cookie('cart_cookie',cart_cookie,max_age=60*60*24*7)

            # 5,返回结果
            return response

    def delete(self,request):
        '''
        删除购物车
        :param request:
        :return:
        '''

        # 1,获取前端数据
        data = request.data

        # 2,验证数据
        ser = CartDeleteSerializers(data=data)
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        print(ser.errors)

        sku_id = ser.validated_data['sku_id']

        # 判断用户是否登录
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 用户已登录
            # 1,建立缓存链接
            conn = get_redis_connection('cart')

            # 2,删除hash类型和集合类型
            conn.hdel('cart_%s'%user.id,sku_id)
            conn.srem('cart_selected_%s'%user.id,sku_id)
            # 3,返回结果
            return Response('ok')

        else:
            # 1,先判断是否有cookie存在
            # 生成响应对象
            response = Response('ok')
            cart_cookie = request.COOKIES.get('cart_cookie')
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
                # 删除cookie中的数据
                if sku_id in cart:
                    del cart[sku_id]

            # 加密写入后的字典
            cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
            response.set_cookie('cart_cookie',cart_cookie,max_age=60*60*24*7)

            # 5,返回结果
            return response



class CartselectionView(APIView):

    def perform_authentication(self, request):
        # 在调用方法之前先不进行用户验证
        pass

    def put(self,request):
        '''
        购物车全选状态
        :param request:
        :return:
        '''

        # 1,获取前端数据
        data = request.data

        # 2,验证数据
        ser = CartSelectedSerializers(data=data)
        # ser.is_valid(raise_exception=True)
        ser.is_valid()
        print(ser.errors)

        selected = ser.validated_data['selected']


        # 判断用户是否登录
        try:
            user = request.user
        except:
            user = None

        if user is not None:
            # 用户已登录
            # 1,建立缓存链接
            conn = get_redis_connection('cart')

            # 2,获取所有的sku_id值
            sku_id_count = conn.hgetall('cart_%s'%user.id)
            sku_ids = sku_id_count.keys()

            # 更新选中状态判断
            if selected:
                conn.sadd('cart_selected_%s'%user.id,*sku_ids)
            else:
                conn.srem('cart_selected_%s' % user.id, *sku_ids)
            # 3,返回结果
            return Response(ser.data)

        # 未登录
        else:
            # 1,先判断是否有cookie存在

            response = Response(ser.data)

            cart_cookie = request.COOKIES.get('cart_cookie')
            if cart_cookie:
                cart = pickle.loads(base64.b64decode(cart_cookie))
                # 更新字典中的所有选中状态
                for sku_id,data_dict in cart.items():
                    data_dict['selected'] = selected

                # 4,将新的字典数据写入cookie
                # 加密写入后的字典
                cart_cookie = base64.b64encode(pickle.dumps(cart)).decode()
                response.set_cookie('cart_cookie',cart_cookie,max_age=60*60*24*7)

            # 5,返回结果
            return response


